#include<iostream>
#include<string>
#include<cstdlib>
#include<cstring>
using namespace std;
extern char**environ;
const int basesize=1024;
const int argvnum=64;
const int envnum=64;
//全局的命令行参数列表
char*gargv[argvnum];
int gargc=0;
//我的系统的环境变量列表
char*genv[envnum];
//全局的shell的工作路径
 char pwd[basesize];
 char pwdenv[basesize];

string GetUserName()
{
  string name=getenv("USER");
  return name.empty()?"None":name;
}
string GetHostName()
{
  string hostname=getenv("HOSTNAME");
  return hostname.empty()?"None":hostname;
}
string GetPwd()
{
   if(nullptr==getcwd(pwd,sizeof(pwd))) return "None";
   snprintf(pwdenv,sizeof(pwdenv),"PWD=%s",pwd);
   putenv(pwdenv);
   return pwd;
}
string MakeCommandLine()
{
  char command_line[basesize];
  snprintf(command_line,basesize,"[%s@%s %s]#",\
      GetUserName().c_str(),GetHostName().c_str(),GetPwd().c_str());
  return command_line;
}
void PrintCommandLine()
{
  printf("%s",MakeCommandLine().c_str());
  fflush(stdout);
}
void InitEnv()
{
   int i=0;
   while(environ[i])
   {
     genv[i]=(char*)malloc(strlen(environ[i])+1);
     strncpy(genv[i],environ[i],strlen(environ[i])+1);
     i++;
   }
   genv[i]=nullptr;
}
bool GetCommandLine(char command_buffer[],int size)
{
  char*result=fgets(command_buffer,size,stdin);
  if(!result)
  {
    return false;
  }
  command_buffer[strlen(command_buffer)-1]='\0';//去掉最后的回车符
  if(strlen(command_buffer)==0)
  {
    return false;
  }
  return true;
}
void AddEnv(const char*it)
{
   int i=0;
   while(genv[i]) i++;
   genv[i]=(char*)malloc(strlen(it)+1);
       strncpy(genv[i],it,strlen(it)+1);
       genv[++i]=nullptr;
}
bool shellcommand()
{
  if(strcmp(gargv[0],"cd")==0)
  {
    if(gargc==2)
    {
      chdir(argv[1]);
    }
    return true;
  }
  else if(strcmp(gargv[0],"export")==0)
  {
    if(gargc==2)
    {
      AddEnv(gargv[1]);//添加环境变量
    }
    return true;
  }
  else if(strcmp(gargv[0],"env")==0)
  {
    for(int i=0;genv[i];i++)
    {
      printf("%s\n",genv[i]);
    }
    return true;
  }
  return false;
}
bool ExecuteCommand()
{
  pid_t id=fork();
  if(id<0) return false;
  if(id==0)
  {
    execvpe(gargv[0],gargv,genv);
    exit(1);
  }
  int status=0;
  pid_t rid=waitpid(id,&status,0);
  if(rid>0)
  {
    return true;

  }
  return false;
}
void ParseCommandLine(char command_buffer[],int len)
{
  (void)len;
  memset(gargv,0,sizeof(gargv));
  argc=0;
  const char*sep=" ";
  gargv[gargc++]=strtok(command_buffer,sep);
  while(gargv[gargc++]=strtok(nullptr,sep));
  gargc--;
}
int main()
{
  InitEnv();//获取环境变量
  char command_buffer[basesize];
  while(true)
  {
    PrintCommandLine();//命令行提示符
    if(!GetCommandLine(command_buffer,basesize))//获取命令
    {
      continue;
    }
    ParseCommandLine(command_buffer,strlen(command_buffer));//分析命令行
     if(shellcommand()) comtinue;//shell执行命令
     ExecuteCommand();//子进程执行命令
  }
  return 0;
}
